#include "ostree.h"
#include "otutil.h"
+#include <gio/gfiledescriptorbased.h>
+
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
return ret;
}
+GVariant *
+ostree_zlib_file_header_new (GFileInfo *file_info,
+ GVariant *xattrs)
+{
+ guint64 size;
+ guint32 uid;
+ guint32 gid;
+ guint32 mode;
+ guint32 rdev;
+ const char *symlink_target;
+ GVariant *ret;
+ ot_lvariant GVariant *tmp_xattrs = NULL;
+
+ size = g_file_info_get_size (file_info);
+ uid = g_file_info_get_attribute_uint32 (file_info, "unix::uid");
+ gid = g_file_info_get_attribute_uint32 (file_info, "unix::gid");
+ mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode");
+ rdev = g_file_info_get_attribute_uint32 (file_info, "unix::rdev");
+
+ if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_SYMBOLIC_LINK)
+ symlink_target = g_file_info_get_symlink_target (file_info);
+ else
+ symlink_target = "";
+
+ if (xattrs == NULL)
+ tmp_xattrs = g_variant_ref_sink (g_variant_new_array (G_VARIANT_TYPE ("(ayay)"), NULL, 0));
+
+ ret = g_variant_new ("(tuuuus@a(ayay))",
+ GUINT64_TO_BE (size), GUINT32_TO_BE (uid),
+ GUINT32_TO_BE (gid), GUINT32_TO_BE (mode), GUINT32_TO_BE (rdev),
+ symlink_target, xattrs ? xattrs : tmp_xattrs);
+ g_variant_ref_sink (ret);
+ return ret;
+}
+
static gboolean
write_padding (GOutputStream *output,
guint alignment,
}
gboolean
-ostree_content_stream_parse (GInputStream *input,
+ostree_content_stream_parse (gboolean compressed,
+ GInputStream *input,
guint64 input_length,
gboolean trusted,
GInputStream **out_input,
if (!g_input_stream_read_all (input, buf, archive_header_size, &bytes_read,
cancellable, error))
goto out;
- file_header = g_variant_new_from_data (OSTREE_FILE_HEADER_GVARIANT_FORMAT,
+ file_header = g_variant_new_from_data (compressed ? OSTREE_ZLIB_FILE_HEADER_GVARIANT_FORMAT : OSTREE_FILE_HEADER_GVARIANT_FORMAT,
buf, archive_header_size, trusted,
g_free, buf);
buf = NULL;
- if (!ostree_file_header_parse (file_header,
- out_file_info ? &ret_file_info : NULL,
- out_xattrs ? &ret_xattrs : NULL,
- error))
- goto out;
- if (ret_file_info)
- g_file_info_set_size (ret_file_info, input_length - archive_header_size - 8);
+ if (compressed)
+ {
+ if (!ostree_zlib_file_header_parse (file_header,
+ out_file_info ? &ret_file_info : NULL,
+ out_xattrs ? &ret_xattrs : NULL,
+ error))
+ goto out;
+ }
+ else
+ {
+ if (!ostree_file_header_parse (file_header,
+ out_file_info ? &ret_file_info : NULL,
+ out_xattrs ? &ret_xattrs : NULL,
+ error))
+ goto out;
+ if (ret_file_info)
+ g_file_info_set_size (ret_file_info, input_length - archive_header_size - 8);
+ }
if (g_file_info_get_file_type (ret_file_info) == G_FILE_TYPE_REGULAR
&& out_input)
* assuming the caller doesn't seek, this should be fine. We might
* want to wrap it though in a non-seekable stream.
**/
- ret_input = g_object_ref (input);
+ if (compressed)
+ {
+ ot_lobj GConverter *zlib_decomp = (GConverter*)g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_RAW);
+ ret_input = g_converter_input_stream_new (input, zlib_decomp);
+ }
+ else
+ ret_input = g_object_ref (input);
}
ret = TRUE;
ot_transfer_out_value (out_xattrs, &ret_xattrs);
out:
return ret;
-
-}
-
-gboolean
-ostree_zlib_content_stream_open (GInputStream *input,
- guint64 *out_len,
- GInputStream **out_uncompressed,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- guint64 uncompressed_len;
- ot_lobj GConverter *zlib_decomp = NULL;
- ot_lobj GInputStream *uncomp_input = NULL;
-
- if (!g_input_stream_read_all (input, &uncompressed_len, sizeof (guint64),
- NULL, cancellable, error))
- goto out;
-
- uncompressed_len = GUINT64_FROM_BE (uncompressed_len);
- zlib_decomp = (GConverter*)g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_RAW);
- uncomp_input = g_converter_input_stream_new (input, zlib_decomp);
-
- if (out_len)
- *out_len = uncompressed_len;
- ot_transfer_out_value (out_uncompressed, &uncomp_input);
- ret = TRUE;
- out:
- return ret;
}
gboolean
-ostree_content_file_parse (GFile *content_path,
+ostree_content_file_parse (gboolean compressed,
+ GFile *content_path,
gboolean trusted,
GInputStream **out_input,
GFileInfo **out_file_info,
{
gboolean ret = FALSE;
guint64 length;
+ struct stat stbuf;
ot_lobj GInputStream *file_input = NULL;
ot_lobj GInputStream *ret_input = NULL;
ot_lobj GFileInfo *content_file_info = NULL;
if (!file_input)
goto out;
- content_file_info = g_file_input_stream_query_info ((GFileInputStream*)file_input,
- OSTREE_GIO_FAST_QUERYINFO,
- cancellable, error);
- if (!content_file_info)
- goto out;
+ if (fstat (g_file_descriptor_based_get_fd ((GFileDescriptorBased*)file_input), &stbuf) < 0)
+ {
+ ot_util_set_error_from_errno (error, errno);
+ goto out;
+ }
- length = g_file_info_get_size (content_file_info);
+ length = stbuf.st_size;
- if (!ostree_content_stream_parse (file_input, length, trusted,
+ if (!ostree_content_stream_parse (compressed, file_input, length, trusted,
out_input ? &ret_input : NULL,
&ret_file_info, &ret_xattrs,
cancellable, error))
return ret;
}
+gboolean
+ostree_zlib_file_header_parse (GVariant *metadata,
+ GFileInfo **out_file_info,
+ GVariant **out_xattrs,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ guint64 size;
+ guint32 uid, gid, mode, rdev;
+ const char *symlink_target;
+ ot_lobj GFileInfo *ret_file_info = NULL;
+ ot_lvariant GVariant *ret_xattrs = NULL;
+
+ g_variant_get (metadata, "(tuuuu&s@a(ayay))", &size,
+ &uid, &gid, &mode, &rdev,
+ &symlink_target, &ret_xattrs);
+
+ size = GUINT64_FROM_BE (size);
+ uid = GUINT32_FROM_BE (uid);
+ gid = GUINT32_FROM_BE (gid);
+ mode = GUINT32_FROM_BE (mode);
+ rdev = GUINT32_FROM_BE (rdev);
+
+ ret_file_info = g_file_info_new ();
+ g_file_info_set_size (ret_file_info, size);
+ g_file_info_set_attribute_uint32 (ret_file_info, "standard::type", ot_gfile_type_for_mode (mode));
+ g_file_info_set_attribute_boolean (ret_file_info, "standard::is-symlink", S_ISLNK (mode));
+ g_file_info_set_attribute_uint32 (ret_file_info, "unix::uid", uid);
+ g_file_info_set_attribute_uint32 (ret_file_info, "unix::gid", gid);
+ g_file_info_set_attribute_uint32 (ret_file_info, "unix::mode", mode);
+
+ if (S_ISREG (mode))
+ {
+ ;
+ }
+ else if (S_ISLNK (mode))
+ {
+ g_file_info_set_attribute_byte_string (ret_file_info, "standard::symlink-target", symlink_target);
+ }
+ else if (S_ISCHR (mode) || S_ISBLK (mode))
+ {
+ g_file_info_set_attribute_uint32 (ret_file_info, "unix::rdev", rdev);
+ }
+ else if (S_ISFIFO (mode))
+ {
+ ;
+ }
+ else
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Corrupted archive file; invalid mode %u", mode);
+ goto out;
+ }
+
+ ret = TRUE;
+ ot_transfer_out_value(out_file_info, &ret_file_info);
+ ot_transfer_out_value(out_xattrs, &ret_xattrs);
+ out:
+ return ret;
+}
+
gboolean
ostree_create_file_from_input (GFile *dest_file,
GFileInfo *finfo,
*/
#define OSTREE_COMMIT_GVARIANT_FORMAT G_VARIANT_TYPE ("(a{sv}aya(say)sstayay)")
+/*
+ * filez objects:
+ * <BE guint32 containing variant length>
+ * t - size
+ * u - uid
+ * u - gid
+ * u - mode
+ * u - rdev
+ * s - symlink target
+ * a(ayay) - xattrs
+ * ---
+ * zlib-compressed data
+ */
+#define OSTREE_ZLIB_FILE_HEADER_GVARIANT_FORMAT G_VARIANT_TYPE ("(tuuuusa(ayay))")
+
const GVariantType *ostree_metadata_variant_type (OstreeObjectType objtype);
gboolean ostree_validate_checksum_string (const char *sha256,
GVariant **out_variant,
GError **error);
-GVariant *ostree_file_header_new (GFileInfo *file_info,
- GVariant *xattrs);
-
gboolean ostree_write_variant_with_size (GOutputStream *output,
GVariant *variant,
guint64 alignment_offset,
GCancellable *cancellable,
GError **error);
+GVariant *ostree_file_header_new (GFileInfo *file_info,
+ GVariant *xattrs);
+GVariant *ostree_zlib_file_header_new (GFileInfo *file_info,
+ GVariant *xattrs);
+
gboolean ostree_file_header_parse (GVariant *data,
GFileInfo **out_file_info,
GVariant **out_xattrs,
GError **error);
+gboolean ostree_zlib_file_header_parse (GVariant *data,
+ GFileInfo **out_file_info,
+ GVariant **out_xattrs,
+ GError **error);
+
gboolean
-ostree_content_stream_parse (GInputStream *input,
+ostree_content_stream_parse (gboolean compressed,
+ GInputStream *input,
guint64 input_length,
gboolean trusted,
GInputStream **out_input,
GCancellable *cancellable,
GError **error);
-gboolean ostree_zlib_content_stream_open (GInputStream *input,
- guint64 *out_len,
- GInputStream **out_uncompressed,
- GCancellable *cancellable,
- GError **error);
-
-gboolean ostree_content_file_parse (GFile *content_path,
+gboolean ostree_content_file_parse (gboolean compressed,
+ GFile *content_path,
gboolean trusted,
GInputStream **out_input,
GFileInfo **out_file_info,
ret_mode = OSTREE_REPO_MODE_BARE;
else if (strcmp (mode, "archive") == 0)
ret_mode = OSTREE_REPO_MODE_ARCHIVE;
- else if (strcmp (mode, "archive-z") == 0)
- ret_mode = OSTREE_REPO_MODE_ARCHIVE_Z;
+ else if (strcmp (mode, "archive-z2") == 0)
+ ret_mode = OSTREE_REPO_MODE_ARCHIVE_Z2;
else
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
checksum_input = ostree_checksum_input_stream_new (input, checksum);
}
- if (objtype == OSTREE_OBJECT_TYPE_FILE
- && repo_mode == OSTREE_REPO_MODE_ARCHIVE_Z)
- {
- gssize bytes_written;
- guint64 len_be;
- ot_lobj GOutputStream *raw_out_stream = NULL;
- ot_lobj GConverter *zlib_compressor = NULL;
- ot_lobj GOutputStream *compressed_out_stream = NULL;
-
- if (!ostree_create_temp_regular_file (self->tmp_dir,
- ostree_object_type_to_string (objtype), NULL,
- &temp_file, &raw_out_stream,
- cancellable, error))
- goto out;
-
- len_be = GUINT64_TO_BE (file_object_length);
- if (!g_output_stream_write_all (raw_out_stream, (const guchar*) &len_be,
- sizeof (guint64), NULL, cancellable, error))
- goto out;
-
- zlib_compressor = (GConverter*)g_zlib_compressor_new (G_ZLIB_COMPRESSOR_FORMAT_RAW, 9);
- compressed_out_stream = g_converter_output_stream_new (raw_out_stream, zlib_compressor);
-
- bytes_written = g_output_stream_splice (compressed_out_stream,
- checksum_input ? (GInputStream*)checksum_input : input,
- G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
- cancellable, error);
- if (bytes_written < 0)
- goto out;
-
- staged_raw_file = TRUE;
- temp_file_is_regular = TRUE;
- }
- else if (objtype == OSTREE_OBJECT_TYPE_FILE)
+ if (objtype == OSTREE_OBJECT_TYPE_FILE)
{
ot_lobj GInputStream *file_input = NULL;
ot_lobj GFileInfo *file_info = NULL;
ot_lvariant GVariant *xattrs = NULL;
- if (!ostree_content_stream_parse (checksum_input ? (GInputStream*)checksum_input : input,
+ if (!ostree_content_stream_parse (FALSE, checksum_input ? (GInputStream*)checksum_input : input,
file_object_length, FALSE,
&file_input, &file_info, &xattrs,
cancellable, error))
goto out;
staged_raw_file = TRUE;
}
+ else if (repo_mode == OSTREE_REPO_MODE_ARCHIVE_Z2)
+ {
+ ot_lvariant GVariant *file_meta = NULL;
+ ot_lobj GOutputStream *temp_out = NULL;
+ ot_lobj GConverter *zlib_compressor = NULL;
+ ot_lobj GOutputStream *compressed_out_stream = NULL;
+
+ if (!ostree_create_temp_regular_file (self->tmp_dir,
+ ostree_object_type_to_string (objtype), NULL,
+ &temp_file, &temp_out,
+ cancellable, error))
+ goto out;
+ temp_file_is_regular = TRUE;
+
+ file_meta = ostree_zlib_file_header_new (file_info, xattrs);
+
+ if (!ostree_write_variant_with_size (temp_out, file_meta, 0, NULL, NULL,
+ cancellable, error))
+ goto out;
+
+ if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR)
+ {
+ zlib_compressor = (GConverter*)g_zlib_compressor_new (G_ZLIB_COMPRESSOR_FORMAT_RAW, 9);
+ compressed_out_stream = g_converter_output_stream_new (temp_out, zlib_compressor);
+
+ if (g_output_stream_splice (compressed_out_stream, file_input,
+ G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
+ cancellable, error) < 0)
+ goto out;
+ }
+
+ if (!g_output_stream_close (temp_out, cancellable, error))
+ goto out;
+ }
else if (repo_mode == OSTREE_REPO_MODE_ARCHIVE)
{
ot_lvariant GVariant *file_meta = NULL;
ot_lvariant GVariant *xattrs = NULL;
gboolean is_regular;
- if (!ostree_content_file_parse (temp_file, FALSE, &file_input,
+ if (!ostree_content_file_parse (FALSE, temp_file, FALSE, &file_input,
&file_info, &xattrs,
cancellable, error))
goto out;
ret_object_dirs = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref);
- if (ostree_repo_get_mode (self) == OSTREE_REPO_MODE_ARCHIVE_Z)
+ if (ostree_repo_get_mode (self) == OSTREE_REPO_MODE_ARCHIVE_Z2)
object_dir_to_scan = self->uncompressed_objects_dir;
else
object_dir_to_scan = self->objects_dir;
case OSTREE_REPO_MODE_ARCHIVE:
skip = !g_str_has_suffix (name, ".filecontent");
break;
- case OSTREE_REPO_MODE_ARCHIVE_Z:
+ case OSTREE_REPO_MODE_ARCHIVE_Z2:
skip = !g_str_has_suffix (name, ".filez");
break;
case OSTREE_REPO_MODE_BARE:
gboolean compressed;
compressed = (type == OSTREE_OBJECT_TYPE_FILE
- && ostree_repo_get_mode (self) == OSTREE_REPO_MODE_ARCHIVE_Z);
+ && ostree_repo_get_mode (self) == OSTREE_REPO_MODE_ARCHIVE_Z2);
relpath = ostree_get_relative_object_path (checksum, type, compressed);
ret = g_file_resolve_relative_path (self->repodir, relpath);
g_free (relpath);
goto out;
if (self->mode == OSTREE_REPO_MODE_ARCHIVE
- || self->mode == OSTREE_REPO_MODE_ARCHIVE_Z)
+ || self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2)
{
if (!write_ref_summary (self, NULL, error))
goto out;
}
}
break;
- case OSTREE_REPO_MODE_ARCHIVE_Z:
+ case OSTREE_REPO_MODE_ARCHIVE_Z2:
{
- ot_lobj GInputStream *file_in = NULL;
- ot_lobj GInputStream *uncomp_input = NULL;
- guint64 uncompressed_len;
-
- file_in = (GInputStream*)gs_file_read_noatime (loose_path, cancellable, error);
- if (!file_in)
- goto out;
-
- if (!ostree_zlib_content_stream_open (file_in, &uncompressed_len, &uncomp_input,
- cancellable, error))
- goto out;
-
- if (!ostree_content_stream_parse (uncomp_input, uncompressed_len, TRUE,
- &ret_input, &ret_file_info, &ret_xattrs,
- cancellable, error))
+ if (!ostree_content_file_parse (TRUE, loose_path, TRUE,
+ out_input ? &ret_input : NULL,
+ &ret_file_info, &ret_xattrs,
+ cancellable, error))
goto out;
}
break;
case OSTREE_REPO_MODE_ARCHIVE:
path = ostree_repo_get_archive_content_path (self, checksum);
break;
- case OSTREE_REPO_MODE_ARCHIVE_Z:
+ case OSTREE_REPO_MODE_ARCHIVE_Z2:
{
if (self->enable_uncompressed_cache)
path = get_uncompressed_object_cache_path (self, checksum);
if (!is_symlink &&
((checkout_data->repo->mode == OSTREE_REPO_MODE_BARE && checkout_data->mode == OSTREE_REPO_CHECKOUT_MODE_NONE)
|| (checkout_data->repo->mode == OSTREE_REPO_MODE_ARCHIVE && checkout_data->mode == OSTREE_REPO_CHECKOUT_MODE_USER)
- || (checkout_data->repo->mode == OSTREE_REPO_MODE_ARCHIVE_Z && checkout_data->mode == OSTREE_REPO_CHECKOUT_MODE_USER)))
+ || (checkout_data->repo->mode == OSTREE_REPO_MODE_ARCHIVE_Z2 && checkout_data->mode == OSTREE_REPO_CHECKOUT_MODE_USER)))
{
if (!find_loose_for_checkout (checkout_data->repo, checksum, &loose_path,
cancellable, error))
*/
if (!is_symlink
&& loose_path == NULL
- && repo->mode == OSTREE_REPO_MODE_ARCHIVE_Z
+ && repo->mode == OSTREE_REPO_MODE_ARCHIVE_Z2
&& checkout_data->mode == OSTREE_REPO_CHECKOUT_MODE_USER
&& repo->enable_uncompressed_cache)
{
typedef enum {
OSTREE_REPO_MODE_BARE,
OSTREE_REPO_MODE_ARCHIVE,
- OSTREE_REPO_MODE_ARCHIVE_Z
+ OSTREE_REPO_MODE_ARCHIVE_Z2
} OstreeRepoMode;
gboolean ostree_repo_mode_from_string (const char *mode,
{
gboolean ret = FALSE;
int i, n;
- gboolean compressed = pull_data->remote_mode == OSTREE_REPO_MODE_ARCHIVE_Z;
+ gboolean compressed = pull_data->remote_mode == OSTREE_REPO_MODE_ARCHIVE_Z2;
ot_lvariant GVariant *tree = NULL;
ot_lvariant GVariant *files_variant = NULL;
ot_lvariant GVariant *dirs_variant = NULL;
{
OtPullData *pull_data = data->pull_data;
const char *checksum = data->checksum;
- gboolean compressed = pull_data->remote_mode == OSTREE_REPO_MODE_ARCHIVE_Z;
+ gboolean compressed = pull_data->remote_mode == OSTREE_REPO_MODE_ARCHIVE_Z2;
ot_lfree char *objpath = NULL;
SoupURI *obj_uri = NULL;
ot_lobj GInputStream *file_object_input = NULL;
ot_lvariant GVariant *xattrs = NULL;
- compressed = data->pull_data->remote_mode == OSTREE_REPO_MODE_ARCHIVE_Z;
+ compressed = data->pull_data->remote_mode == OSTREE_REPO_MODE_ARCHIVE_Z2;
was_content_fetch = data->fetching_content;
if (was_content_fetch)
if (!need_content_fetch && compressed)
{
- ot_lobj GInputStream *uncomp_input = NULL;
+ ot_lobj GInputStream *file_in = NULL;
+ ot_lobj GFileInfo *file_info = NULL;
+ ot_lvariant GVariant *xattrs = NULL;
+ ot_lobj GInputStream *object_input = NULL;
g_assert (data->content_path != NULL);
- content_input = (GInputStream*)g_file_read (data->content_path, cancellable, error);
- if (!content_input)
+ if (!ostree_content_file_parse (TRUE, data->content_path, FALSE,
+ &file_in, &file_info, &xattrs,
+ cancellable, error))
goto out;
- if (!ostree_zlib_content_stream_open (content_input, &length, &uncomp_input,
- cancellable, error))
+ if (!ostree_raw_file_to_content_stream (file_in, file_info, xattrs,
+ &object_input, &length,
+ cancellable, error))
goto out;
data->pull_data->outstanding_content_stage_requests++;
ostree_repo_stage_content_async (data->pull_data->repo, data->checksum,
- uncomp_input, length,
+ object_input, length,
cancellable,
content_fetch_on_stage_complete, data);
}
SoupURI *obj_uri = NULL;
gboolean compressed;
- compressed = pull_data->remote_mode == OSTREE_REPO_MODE_ARCHIVE_Z;
+ compressed = pull_data->remote_mode == OSTREE_REPO_MODE_ARCHIVE_Z2;
ostree_object_name_deserialize (fetch_data->object, &checksum, &objtype);
switch (pull_data->remote_mode)
{
case OSTREE_REPO_MODE_ARCHIVE:
- case OSTREE_REPO_MODE_ARCHIVE_Z:
+ case OSTREE_REPO_MODE_ARCHIVE_Z2:
break;
default:
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
echo '1..11'
-setup_test_repository "archive-z"
+setup_test_repository "archive-z2"
echo "ok setup"
. ${SRCDIR}/archive-test.sh
echo '1..2'
-setup_fake_remote_repo1 "archive-z"
+setup_fake_remote_repo1 "archive-z2"
. ${SRCDIR}/pull-test.sh